﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Runtime.InteropServices;

//Code from http://www.neowin.net/forum/lofiversion/index.php/t369213.html
namespace WindowsFormsApplication1
{
    class ApplicationSensor :Sensor, IObserver
    {
        private const int GWL_EXSTYLE = (-20);
        private const int WS_EX_TOOLWINDOW = 0x80;
        private const int WS_EX_APPWINDOW = 0x40000;
        private const int GW_OWNER = 4;
        public delegate int EnumWindowsProcDelegate(int hWnd, int lParam);
        [DllImport("user32")]
        private static extern int EnumWindows(EnumWindowsProcDelegate lpEnumFunc, int lParam);
        [DllImport("User32.Dll")]
        public static extern void GetWindowText(int h, StringBuilder s, int nMaxCount);
        [DllImport("user32", EntryPoint = "GetWindowLongA")]
        private static extern int GetWindowLongPtr(int hwnd, int nIndex);
        [DllImport("user32")]
        private static extern int GetParent(int hwnd);
        [DllImport("user32")]
        private static extern int GetWindow(int hwnd, int wCmd);
        [DllImport("user32")]
        private static extern int IsWindowVisible(int hwnd);
        [DllImport("user32")]
        private static extern int GetDesktopWindow();
        private Timer myTimer;
        private List<string> app_list;
        public ApplicationSensor()
        {
            name = "Application Sensor";
            app_list = new List<string>();
            /*myTimer = new Timer();
            myTimer.Elapsed += new ElapsedEventHandler(AppEventArrived);
            myTimer.Interval = 4000;
            myTimer.Start();*/
            EnumWindows(EnumWindowsProc, 0);
            data = app_list;
            Notify();
        }
        //Designed to be sent only by the processSensor, gives array of running processes
        //Checks to see if iTunes is one of the new processes
        public void Update(string sender, object msg)
        {
            EnumWindows(EnumWindowsProc, 0);
            data = app_list;
            if (app_list.Count == 0) data = null;
            Notify();
        }
        private static bool IsTaskbarWindow(int hWnd)
        {
            int lExStyle;
            int hParent;
            lExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
            hParent = GetParent(hWnd);
            bool fTaskbarWindow = ((IsWindowVisible(hWnd) != 0) & (GetWindow(hWnd, GW_OWNER) == 0) & (hParent == 0 | hParent == GetDesktopWindow()));
            if ((lExStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW)
            {
                fTaskbarWindow = false;
            }
            if ((lExStyle & WS_EX_APPWINDOW) == WS_EX_APPWINDOW)
            {
                fTaskbarWindow = true;
            }
            return fTaskbarWindow;
        }
        public int EnumWindowsProc(int hWnd, int lParam)
        {
            if (IsTaskbarWindow(hWnd))
            {
                StringBuilder sb = new StringBuilder(1024);
                GetWindowText(hWnd, sb, sb.Capacity);
                String xMsg = sb.ToString();
                {
                    if (xMsg.Length > 0)
                    {
                        //Console.WriteLine(xMsg);
                        app_list.Add(xMsg);
                    }
                }
            }
            return 1;
        }
        public void run()
        {
            EnumWindows(EnumWindowsProc, 0);
        }
        private void AppEventArrived(object source, ElapsedEventArgs f)
        {
            EnumWindows(EnumWindowsProc, 0);
            data = app_list;
            if (app_list.Count == 0) data = null;
            Notify();
        }
    }
}
